﻿using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

public class EncryptOrDecrypt {

    // 固定的密码和盐值，动态生成密码会更安全  这里使用 工具生成的固定密码
    private const string FixedPassword = "MyFixedPassword";
    private const string FixedSalt = "x#TE9b8^7E4WtvB^sQYbty#8UZsz%6@d";

    // AES实例  
    private Aes _aes;

    /// <summary>
    /// 私有构造函数
    /// </summary>
    private EncryptOrDecrypt() {
        // 生成AES密钥和IV  
        using (var rfc2898DeriveBytes = new Rfc2898DeriveBytes(FixedPassword, Encoding.UTF8.GetBytes(FixedSalt))) {
            byte[] key = rfc2898DeriveBytes.GetBytes(32); // AES256要求32字节密钥  
            byte[] iv = rfc2898DeriveBytes.GetBytes(16);  // AES要求16字节IV  

            _aes = Aes.Create();
            _aes.Key = key;
            _aes.Mode = CipherMode.CBC;
            _aes.Padding = PaddingMode.PKCS7;
            _aes.IV = iv;
        }
    }

    // 静态只读字段，用于存储单例实例  
    private static readonly EncryptOrDecrypt _instance = new EncryptOrDecrypt();

    // 公共静态属性，用于获取单例实例  
    public static EncryptOrDecrypt Instance => _instance;

    /// <summary>
    /// 字符串加密方法
    /// </summary>
    public string Encrypt(string plainText) {
        if (string.IsNullOrEmpty(plainText)) return null;

        byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);

        using (var encryptor = _aes.CreateEncryptor(_aes.Key, _aes.IV))
        using (var msEncrypt = new MemoryStream()) {
            using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) {
                csEncrypt.Write(plainTextBytes, 0, plainTextBytes.Length);
            }
            return Convert.ToBase64String(msEncrypt.ToArray());
        }
    }

    /// <summary>
    /// 字符串解密方法
    /// </summary>
    public string Decrypt(string cipherText) {
        if (string.IsNullOrEmpty(cipherText)) return null;

        var cipherTextBytes = Convert.FromBase64String(cipherText);

        using (var decryptor = _aes.CreateDecryptor(_aes.Key, _aes.IV))
        using (var msDecrypt = new MemoryStream(cipherTextBytes)) {
            using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
            using (var msRead = new MemoryStream()) {
                csDecrypt.CopyTo(msRead);
                return Encoding.UTF8.GetString(msRead.ToArray());
            }
        }
    }
}